package cn.ilikes.tools.nosql.jpa.classloads.porxys;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.PersistenceException;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.NoOp;
import cn.ilikes.tools.nosql.jpa.JPASQLPersistenUnitEnv;
import cn.ilikes.tools.nosql.jpa.clients.AbClient;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.nosql.jpa.unitls.lists.JPASQLArraryList;
import cn.ilikes.tools.nosql.jpa.unitls.lists.JPArraryList;

public class CglibLayInitializerList implements LazyInitializers, InvocationHandler {

	private List<String> filterMethods = new ArrayList<String>();

	private JPArraryList arraryList;

	private Enhancer enhancer;

	private final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
		public int accept(Method method) {
			String methodName = method.getName();
			if (filterMethods.contains(methodName))
				return 0;
			else
				return 0;
		}
	};

	public CglibLayInitializerList(AbClient client, EntityFields entityFields, Object entity, JPASQLPersistenUnitEnv persistenUnitEnv) {

		JPArraryList objects = new JPArraryList(client, entityFields, entity, persistenUnitEnv);
		setArraryList(objects);
		init();
		filterMethods();

	}

	private void setArraryList(JPArraryList arraryList) {
		this.arraryList = arraryList;
	}

	private JPArraryList getArraryList() {
		return arraryList;
	}

	private void filterMethods() {
		filterMethods.add("toString");
		filterMethods.add("iterator");

	}

	private void setEnhancer(Enhancer enhancer) {
		this.enhancer = enhancer;

	}

	private void init() {
		Enhancer e = new Enhancer();
		e.setSuperclass(JPASQLArraryList.class);
		e.setInterfaces(JPASQLArraryList.class.getClass().getInterfaces());
		e.setCallbackTypes(new Class[] { InvocationHandler.class, NoOp.class });
		e.setCallbackFilter(FINALIZE_FILTER);
		e.setCallbacks(new Callback[] { this, NoOp.INSTANCE });
		e.setUseFactory(false);
		e.setInterceptDuringConstruction(false);
		setEnhancer(e);
	}

	@Override
	public Object getProxy() throws PersistenceException {
		try {

			Object object = enhancer.create();
			return object;
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}

	@Override
	public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
		JPArraryList arraryList = getArraryList();
		return arg1.invoke(arraryList, arg2);
	}

}
